﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Money.Interfaces;
using One.Framework;
using Money.Data;
using System.Data.Linq.SqlClient;

namespace Money.Services
{
    public class TransactionService : ITransactionService
    {
        private Money.Data.MoneyManagerDataContext context;

        public TransactionService()
        {
            context = new Money.Data.MoneyManagerDataContext();
        }

        public void CreateTransaction(Money.Data.Transaction item)
        {
            try
            {
                using (MoneyManagerDataContext contx = new MoneyManagerDataContext())
                {
                    item.CreationOn = DateTime.Now;
                    if (item.Account1 != null)
                        item.Account1 = contx.Accounts.SingleOrDefault(a => a.AccountId == item.Account1.AccountId);
                    contx.Transactions.InsertOnSubmit(item);
                    contx.SubmitChanges();
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot create transaction");
            }
        }

        public void DeleteTransaction(long id)
        {
            try
            {
                Transaction item = GetTransactionById(id);
                context.Transactions.DeleteOnSubmit(item);
                context.SubmitChanges();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot delete transaction");
            }
        }

        public void UpdateTransaction(Money.Data.Transaction item)
        {
            try
            {
                using (MoneyManagerDataContext contx = new MoneyManagerDataContext())
                {
                    item.ModifiedOn = DateTime.Now;
                    item.Account = contx.Accounts.SingleOrDefault(a => a.AccountId == item.AccountId);
                    item.Category = contx.Categories.SingleOrDefault(c => c.Id == item.CategoryId);
                    item.Ref = contx.Refs.SingleOrDefault(r => r.RefId == item.RefId);
                    item.Class = contx.Classes.SingleOrDefault(c => c.Id == item.ClassId);
                    if (item.Account1 != null)
                        item.Account1 = contx.Accounts.SingleOrDefault(a => a.AccountId == item.Account1.AccountId);
                    contx.Transactions.Attach(item);
                    contx.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, item);

                    contx.SubmitChanges();
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot update transaction");
            }
        }

        public Money.Data.Transaction GetTransactionById(long id)
        {
            try
            {
                return context.Transactions.Where(t => t.Id == id).SingleOrDefault<Transaction>();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot get transaction");
            }
        }

        public List<Money.Data.Transaction> GetTransactions(string orderBy, string orderDirection, int page, int pageSize, out int totalRecords)
        {
            try
            {
                var query = from u in context.Transactions
                            select u;
                return query.OrderByPaging<Transaction>(orderBy, orderDirection, page, pageSize, out totalRecords).ToList<Transaction>();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot get transactions");
            }
        }

        public List<Money.Data.Transaction> GetTransactions(int accountId, int transactionType, string payer, string orderBy, string orderDirection, int page, int pageSize, out int totalRecords)
        {
            try
            {
                var query = from u in context.Transactions
                            where u.AccountId == accountId && u.TransactionType == transactionType && u.PayMan == payer
                            select u;
                return query.OrderByPaging<Transaction>(orderBy, orderDirection, page, pageSize, out totalRecords).ToList<Transaction>();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot get transactions");
            }
        }

        public List<Money.Data.Transaction> GetTransactions(int userId, int accountFromId, int accountToId, int transactionType, string payer, string orderBy, string orderDirection, int page, int pageSize, out int totalRecords)
        {
            try
            {
                var query = context.Transactions.Where(t => t.Account.UserId == userId);
                if (accountFromId > 0)
                    query = query.Where(t => t.Account.AccountId == accountFromId);
                if (accountToId > 0)
                    query = query.Where(t => t.AccountIdTo == accountToId);
                if (transactionType > 0)
                    query = query.Where(t => t.TransactionType == transactionType);
                if(!string.IsNullOrEmpty(payer))
                    query = query.Where(t => SqlMethods.Like(t.PayMan, "%" + payer + "%"));
                return query.OrderByPaging<Transaction>(orderBy, orderDirection, page, pageSize, out totalRecords).ToList<Transaction>();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
                throw new Exception("Cannot get transactions");
            }
        }
    }
}
